SIM_TOP_NAME = MySoCSim
BUILD_DIR = ./build
EMU_BUILD_DIR = $(BUILD_DIR)/emu
SOC_BUILD_DIR = $(BUILD_DIR)/soc
SIM_TOP_V = $(EMU_BUILD_DIR)/verilog/$(SIM_TOP_NAME).v
SoCMyCore = $(EMU_BUILD_DIR)/verilog/ysyx_210718.v	#MySoC

SCALA_FILE = $(shell find ./src/main/scala -name '*.scala')
TEST_FILE = $(shell find ./src/test/scala -name '*.scala')

DATAWIDTH ?= 64
BOARD ?= sim
TRACE ?= 0


ysyx:
	@mkdir -p $(SOC_BUILD_DIR)/verilog
	mill chiselModule.runMain top.TopMain BOARD=ysyx -td $(SOC_BUILD_DIR)/verilog
	@mv $(SOC_BUILD_DIR)/verilog/MySoC.v $(SOC_BUILD_DIR)/verilog/ysyx_210718.v 
	

#sbt "runMain top.TopMain BOARD=sim"
$(SIM_TOP_V): $(SCALA_FILE)
	@mkdir -p $(@D)
	mill chiselModule.runMain top.TopMain BOARD=sim -td $(EMU_BUILD_DIR)/verilog

# files
EMU_CSRC_DIR = $(abspath ./emulator/src/emu)
EMU_VSRC_DIR = $(abspath ./emulator/vsrc)
EMU_CXXFILES = $(shell find $(EMU_CSRC_DIR) -name "*.cpp")
EMU_VFILES = $(shell find $(EMU_VSRC_DIR) -name "*.v" -or -name "*.sv")

EMU_CXXFLAGS = -O3 -std=c++11 -static -g -Wall -I$(EMU_CSRC_DIR)
EMU_CXXFLAGS += -DVERILATOR -Wno-maybe-uninitialized -D__RV$(DATAWIDTH)__
EMU_LDFLAGS = -lpthread -lSDL2 -ldl

# EMU : verilator
EMU := $(EMU_BUILD_DIR)/emu
EMU_MK := $(EMU_BUILD_DIR)/V$(SIM_TOP_NAME)/V$(SIM_TOP_NAME).mk
EMU_DEPS := $(EMU_VFILES) $(EMU_CXXFILES)
EMU_HEADERS := $(shell find $(EMU_CSRC_DIR) -name "*.h")


ifeq ($(TRACE), 1)
EMU_CXXFLAGS += -DVCD
#VERILATOR_FLAGS += \
#	+define+VM_TRACE=1
endif
# 默认打开difftest宏
DIFF ?= 1
ifeq ($(DIFF), 1)
#VERILATOR_FLAGS += +define+__DIFFTEST__=1
EMU_CXXFLAGS += -D__DIFFTEST__
endif

# verilator arguments: 
# +define+<var>=<value>      Set preprocessor define
# +define+<var>=<value>      Set preprocessor define
# --output-split <statements>          Split .cpp files into pieces
# --output-split-cfuncs <statements>   Split .cpp functions
# -I<dir>                    Directory to search for includes
# --x-assign <mode>           Assign non-initial Xs to this value
# -LDFLAGS <flags>           Linker pre-object flags for makefile
# --trace  #Enable waveform creation
VERILATOR_FLAGS = --top-module $(SIM_TOP_NAME) \
    +define+RV$(DATAWIDTH)=1 \
    --assert \
    --output-split 5000 \
    -I$(abspath $(EMU_BUILD_DIR)) \
    --x-assign unique -O3 -CFLAGS "$(EMU_CXXFLAGS)" \
    -LDFLAGS "$(EMU_LDFLAGS)" \
    --trace


$(EMU_MK): $(SIM_TOP_V) | $(EMU_DEPS)
	@mkdir -p $(@D)
	verilator --cc --exe $(VERILATOR_FLAGS) -o $(abspath $(EMU)) -Mdir $(@D) $(abspath $(SIM_TOP_V)) $(EMU_DEPS)

lint: $(SIM_TOP_V) | $(EMU_DEPS)
	@mkdir -p $(@D)
	verilator --lint-only --cc --exe -Wall $(VERILATOR_FLAGS) -o $(abspath $(EMU)) -Mdir $(@D) $(abspath $(SIM_TOP_V)) $(EMU_DEPS)

# difftest: nemu
USE_READY_TO_RUN_NEMU = false
ifeq ($(USE_READY_TO_RUN_NEMU), true)
REF_SO := ./ready-to-run/riscv$(DATAWIDTH)-nemu-interpreter-so
else
REF_SO := $(NEMU_HOME)/build/riscv$(DATAWIDTH)-nemu-interpreter-so
$(REF_SO):
	$(MAKE) -C $(NEMU_HOME) ISA=riscv$(DATAWIDTH) SHARE=1
endif

# range number [1 : 10000]
SEED = -s $(shell seq 1 10000 | shuf | head -n 1)
# log will only be printed when (LOG_BEGIN<=GTimer<=LOG_END) && (LOG_LEVEL < loglevel)
# use 'emu -h' to see more details
LOG_BEGIN ?= 0
LOG_END ?= 0
LOG_LEVEL ?= ALL

# assign image abspath
IMAGE ?= ./readybin/rtthread.bin
#IMAGE ?= ~/pa/am-kernels/tests/cpu-tests/build/add-riscv64-mycpu.bin


$(EMU): $(EMU_MK) $(EMU_DEPS) $(EMU_HEADERS) $(REF_SO)
	CPPFLAGS=-DREF_SO=\\\"$(REF_SO)\\\" $(MAKE) VM_PARALLEL_BUILDS=1 -C $(dir $(EMU_MK)) -f $(abspath $(EMU_MK))

emu: $(EMU) $(SIM_TOP_V)
	$(EMU) -i $(IMAGE) $(SEED) -b $(LOG_BEGIN) -e $(LOG_END) -v $(LOG_LEVEL)

reemu: $(EMU) $(SIM_TOP_V)
	-@rf -rf $(EMU_BUILD_DIR)/V$(SIM_TOP_NAME) $(EMU)
	$(EMU) -i $(IMAGE) $(SEED) -b $(LOG_BEGIN) -e $(LOG_END) -v $(LOG_LEVEL)

gdb:
	gdb -args $(EMU) -i $(IMAGE) $(SEED) -b $(LOG_BEGIN) -e $(LOG_END) -v $(LOG_LEVEL)

clean:
	-rm -rf $(EMU) $(EMU_BUILD_DIR)/V$(SIM_TOP_NAME) vlt_dump.vcd 

distclean:
	-rm -rf $(BUILD_DIR) 

GREEN = "\033[32m
RED = "\031[32m
NONE = \033[0m"
# ========================================================
#                         SoC 
# ========================================================

YSYXSoC_DIR = /home/asker/chisels/ysyxSoC
MyCPU = $(SOC_BUILD_DIR)/verilog/ysyx_210718.v
# SoC Environment
SOC_TOP_NAME = TestHarness#ysyxSoCFull
SoC_TOP = $(YSYXSoC_DIR)/ysyx/soc/ysyxSoCFull.v

YSYX_RAM = $(YSYXSoC_DIR)/ysyx/ram/S011HD1P_X32Y2D128.v
SOC_VFILES += $(shell find $(YSYXSoC_DIR)/ysyx/peripheral -name "*.v" -or -name "*.sv") # 2
SOC_VFILES += $(SoC_TOP) $(MyCPU) $(YSYX_RAM) # 3 4

SOC_CSRC_DIR = $(abspath ./emulator/src/soc)
SOC_CXXFILES = $(shell find $(SOC_CSRC_DIR) -name "*.cpp")

SOC_EMU := $(SOC_BUILD_DIR)/SocEmu
SOC_MK := $(SOC_BUILD_DIR)/V$(SOC_TOP_NAME)/V$(SOC_TOP_NAME).mk
SOC_DEPS := $(SOC_VFILES) $(SOC_CXXFILES)

uart16550_dir = $(YSYXSoC_DIR)/ysyx/peripheral/uart16550/rtl
spi_dir = $(YSYXSoC_DIR)/ysyx/peripheral/spi/rtl
soc_verilator_dir = $(SOC_BUILD_DIR)/V$(SOC_TOP_NAME)

SOC_CXXFLAGS += -DVERILATOR -Wno-maybe-uninitialized 

SOC_VERILATOR_FLAGS = --top-module $(SOC_TOP_NAME) \
    +define+RV$(DATAWIDTH)=1 \
    --assert \
    --timescale "1ns/1ns" \
    --output-split 5000 \
    -I$(abspath $(uart16550_dir)) \
	-I$(abspath $(spi_dir)) \
	-I$(abspath $(soc_verilator_dir)) \
    --x-assign unique -O3 -CFLAGS "$(SOC_CXXFLAGS)" \
    -LDFLAGS "$(EMU_LDFLAGS)" \
    --trace

ifeq ($(SOC_VCD), 1)
SOC_CXXFLAGS += -DSOC_VCD
#VERILATOR_FLAGS += +define+SOC_VCD=1
endif

$(SOC_MK): $(SoC_TOP) | $(SOC_DEPS)
	@mkdir -p $(@D)
	@echo $(GREEN) VERILATOR BUILD... $(NONE)
	@verilator --cc --exe  $(SOC_VERILATOR_FLAGS) -o $(abspath $(SOC_EMU)) -Mdir $(@D) $(SOC_DEPS)


$(SOC_EMU): $(SOC_MK) 
	$(MAKE) VM_PARALLEL_BUILDS=1 -C $(dir $(SOC_MK)) -f $(abspath $(SOC_MK))

FLASH ?= flash
BIN ?= hello
FLASH_IMAGE = $(YSYXSoC_DIR)/ysyx/program/bin/$(FLASH)/$(BIN)-$(FLASH).bin

soc: $(SOC_EMU) $(SoC_TOP)
	$(SOC_EMU) -i $(FLASH_IMAGE)

soc_gdb:
	gdb -args $(SOC_EMU) -i $(FLASH_IMAGE)

soc_clean:
	-rm -rf $(SOC_BUILD_DIR)/V$(SOC_TOP_NAME) $(SOC_EMU) $(SOC_BUILD_DIR)/soc_dump.vcd

.PHONY: ysyx emu reemu gdb soc soc_gdb clean soc_clean lint#$(REF_SO)